#include "pch.h"
#include "AirEffect.h"
#include "RendererEngine.h"

namespace mini
{
	CAirEffect::CAirEffect()
	{
		bindMaterial(R"(resource\Material\airEffect.ma)");
		CDevice* pDevice = GEngine->getDevice();
		int nWidth = pDevice->getConfig().screenWidth;
		int nHeight = pDevice->getConfig().screenHeight;
		mpSceneTexture = new CTexture();
		if (nullptr != mpSceneTexture)
		{
			mpSceneTexture->initialiseRenderTexture(nWidth, nHeight, DXGI_FORMAT_R8G8B8A8_UNORM);
			mpSceneTexture->setSampleState(mpMaterialUnit->getSampler(0));
		}
	}

	CAirEffect::~CAirEffect()
	{
		SafeRelease(mpMeshUnit);
		for (auto item : mTextureArray)
		{
			SafeRelease(item);
		}
		mTextureArray.clear();
		mpRenderTargetViewArray.clear();
		SafeRelease(mpSceneTexture);
	}

	void CAirEffect::update(float fDeltaTime)
	{

	}

	void CAirEffect::commitToGpu(DeviceContext* pContext)
	{
		int nSize = mpRenderTargetViewArray.size();
		if (nSize > 0)
		{
			for (auto item : mTextureArray)
			{
				item->clearRenderTargetView(CPoint4F(0, 0, 0, 0));
			}
			pContext->OMSetRenderTargets(nSize, &mpRenderTargetViewArray[0], GEngine->getDevice()->getDepthStencilView());
		}
		CShaderUnit* pShaderUnit = nullptr;
		auto _render = [&](std::map<CShaderUnit*, std::list<CMeshUnit*>>& renderUnit)
		{
			for (auto& item : renderUnit)
			{
				for (auto& child : (item.second))
				{
					pShaderUnit->setShader(pContext);
					pShaderUnit->setWorldMatrix(&child->getMatrix());
					pShaderUnit->setViewMatrix(GEngine->getViewMatrix());
					pShaderUnit->setProjectMatrix(GEngine->getProjectMatrix());
					pShaderUnit->apply(pContext);
					static float xx[4];
					xx[0] += 0.01f;
					pShaderUnit->updatePSConstBuffer("randValue", xx);
					CMaterialUnit* pUnit = child->getMaterialUnit();
					if (pUnit != nullptr)
					{
						pUnit->AddRef();
						child->bindMaterial(mpMaterialUnit);
						mpSceneTexture->commitToGpu(pContext, 0);
						child->render(pContext);
						child->buildMaterialUnit(pUnit);
					}
				}
			}
		};
		
		mpSceneTexture->copyFrom(GEngine->getDevice()->getBackBufferTexture2D(), pContext);
		
		int nPassCount = mpMaterialUnit->getShaderUnitSize();
		for (int i = 0; i < nPassCount; ++i)
		{
			pShaderUnit = mpMaterialUnit->getShaderUnit(i);

			if (nullptr != pShaderUnit)
			{
				for (auto& item : mZbufferOffRenderUnits)
				{
					auto _item = (item.second);
					(_item.second)->render(pContext);
				}
				_render(mRenderUnits);
				_render(mAlphaRenderUnits);
			}
		}
		cleanUnit();

		//if (mpMeshUnit)
		//{
		//	GEngine->getDevice()->recoverBackBuffer(pContext);
		//	auto pMaterialUnit = mpMeshUnit->getMaterialUnit();
		//	auto pShaderUnit = pMaterialUnit->getShaderUnit(0);
		//	pShaderUnit->setWorldMatrix(&mpMeshUnit->getMatrix());
		//	pShaderUnit->setViewMatrix(GEngine->getViewMatrix());
		//	pShaderUnit->setOrthoMatrix(GEngine->getOrthoMatrix());
		//	pShaderUnit->setShader(pContext);
		//	pShaderUnit->apply(pContext);
		//	mpMeshUnit->render(pContext);
		//}
	}

	void CAirEffect::addUnit(CUnit* pUnit, EntityType Type, INT32 zLayer)
	{
		CEffect::addUnit(pUnit, Type, zLayer);
	}

}